package handler

import (
	"crypto/sha1"
	"encoding/xml"
	"enterprise-wechat-pay-sdk/config"
	"fmt"
	"io"
	"net/http"
	"sort"
	"strings"

	"github.com/gin-gonic/gin"
)

// CallbackRequest 回调请求结构
type CallbackRequest struct {
	MsgSignature string `form:"msg_signature"`
	Timestamp    string `form:"timestamp"`
	Nonce        string `form:"nonce"`
	EchoStr      string `form:"echostr"`
}

// CallbackXML 回调XML结构
type CallbackXML struct {
	ToUserName string `xml:"ToUserName"`
	AgentID    string `xml:"AgentID"`
	Encrypt    string `xml:"Encrypt"`
}

// CallbackResponse 回调响应结构
type CallbackResponse struct {
	Encrypt      string `xml:"Encrypt"`
	MsgSignature string `xml:"MsgSignature"`
	TimeStamp    string `xml:"TimeStamp"`
	Nonce        string `xml:"Nonce"`
}

// VerifyCallback 验证回调URL
func VerifyCallback(c *gin.Context) {
	var req CallbackRequest
	if err := c.ShouldBindQuery(&req); err != nil {
		c.String(http.StatusBadRequest, "Invalid request")
		return
	}

	// 验证签名
	if !verifySignature(req.MsgSignature, req.Timestamp, req.Nonce, req.EchoStr) {
		c.String(http.StatusBadRequest, "Invalid signature")
		return
	}

	// 解密echostr
	decryptedMsg, err := decryptMessage(req.EchoStr)
	if err != nil {
		c.String(http.StatusInternalServerError, "Decrypt failed")
		return
	}

	// 返回解密后的消息
	c.String(http.StatusOK, decryptedMsg)
}

// HandleCallback 处理回调消息
func HandleCallback(c *gin.Context) {
	var req CallbackRequest
	if err := c.ShouldBindQuery(&req); err != nil {
		c.String(http.StatusBadRequest, "Invalid request")
		return
	}

	// 读取请求体
	body, err := io.ReadAll(c.Request.Body)
	if err != nil {
		c.String(http.StatusBadRequest, "Invalid request body")
		return
	}

	// 解析XML
	var xmlData CallbackXML
	if err := xml.Unmarshal(body, &xmlData); err != nil {
		c.String(http.StatusBadRequest, "Invalid XML")
		return
	}

	// 验证签名
	if !verifySignature(req.MsgSignature, req.Timestamp, req.Nonce, xmlData.Encrypt) {
		c.String(http.StatusBadRequest, "Invalid signature")
		return
	}

	// 解密消息
	_, err = decryptMessage(xmlData.Encrypt)
	if err != nil {
		c.String(http.StatusInternalServerError, "Decrypt failed")
		return
	}

	// 处理业务逻辑
	// TODO: 根据消息类型处理不同的业务逻辑

	// 返回成功响应
	c.String(http.StatusOK, "success")
}

// verifySignature 验证签名
func verifySignature(signature, timestamp, nonce, encrypt string) bool {
	// 1. 将token、timestamp、nonce、encrypt四个参数进行字典序排序
	params := []string{config.GlobalConfig.Wechat.Token, timestamp, nonce, encrypt}
	sort.Strings(params)

	// 2. 将四个参数拼接成一个字符串进行sha1加密
	str := strings.Join(params, "")
	h := sha1.New()
	h.Write([]byte(str))
	calculatedSignature := fmt.Sprintf("%x", h.Sum(nil))

	// 3. 将sha1加密后的字符串可与signature对比
	return calculatedSignature == signature
}

// decryptMessage 解密消息
func decryptMessage(encrypt string) (string, error) {
	// TODO: 实现消息解密逻辑
	// 1. 使用EncodingAESKey进行解密
	// 2. 去除16位随机字符串
	// 3. 去除corpid
	return "", nil
}
